﻿Imports System.Text

Public Class clsPeakCrossover
    Private Enum eChild
        son
        daughter
    End Enum
    Public Function Crossover(ByRef projList As List(Of KeyValuePair(Of Single, clsProject)),
                              ByRef pairList As Dictionary(Of Int32, clsProjectPair),
                              ByVal lTreshold As Single, ByVal uTreshold As Single,
                              ByRef res_hash As Dictionary(Of Int32, Int32()),
                              ByRef cloneList As HashSet(Of Int32)) As List(Of KeyValuePair(Of Single, clsProject))
        Try
            '0,9 = 33,7
            For Each pair As clsProjectPair In pairList.Values
                Dim treshold As Decimal = 0 'tres 'GetLevel(lTreshold, uTreshold)
                Dim ret As HashSet(Of clsProjectPair) = GenerateChilds(pair, treshold, res_hash, lTreshold, uTreshold, cloneList)
                For Each p In ret
                    'Dim x = From a In projList Where a.Value.ActivtyList Is p.father.ActivtyList Select True
                    'If x.Count = 0 Then
                    Dim bAdd As Boolean = True
                    If detectClones Then
                        bAdd = IsClone(cloneList, p.father.ActivtyList)
                    End If
                    If bAdd Then
                        projList.Add(New KeyValuePair(Of Single, clsProject)(p.father.Fitness, p.father))
                    End If

                    bAdd = True
                    If detectClones Then
                        bAdd = IsClone(cloneList, p.mother.ActivtyList)
                    End If
                    'end If
                    If bAdd Then
                        projList.Add(New KeyValuePair(Of Single, clsProject)(p.mother.Fitness, p.mother))
                    End If

                Next
            Next
            Return projList
        Catch ex As Exception
            Throw
        End Try
    End Function
    Private Function _ALtoSCH(ByVal al As HashSet(Of Int32), ByRef proj As clsProject, ByRef res_hash As Dictionary(Of Int32, Int32())) As Int32
        Try
            Dim diagrams As New Dictionary(Of String, Int32()())
            Dim makespan As New clsMakeSpanWithRes
            Dim span = makespan.CalcMakeSpan(al, proj, diagrams, res_hash, clsMakeSpanWithRes.eDirection.Left, False)
            proj.Fitness = span
            proj.ActivtyList = GetAL(proj)
            ' proj.ActivtyList = al
            If proj.TasksA.Last.PlanedAt < span Then
                Debug.Print("falsch")
            End If
            If check Then
                Dim valid As Boolean = SuccessorValidation(proj)
                Dim resvalid As Boolean = ResourceValidation(proj)

                If Not (valid And resvalid) Then
                    Debug.Print("Invalid")
                End If
            End If
            proj.PlanedTimes = PlanedToString(proj)
            Return span
        Catch ex As Exception
            Throw
        End Try
    End Function
    Private Function Zufallszahl(ByVal min, ByVal max) As Single
        Dim z As Single
        z = RandNum.NextDouble()
        min *= 1000
        max *= 1000
        Zufallszahl = Int(min + (max - min + 1) * z) / 1000
        Return Zufallszahl
    End Function
    Private Function IsCandidate(ByVal list As HashSet(Of Int32), ByVal task As clsTask, ByVal peaklist As HashSet(Of HashSet(Of Int32))) As Boolean
        Try
            Dim bCandidate As Boolean = True

            Dim inPeak = Function(y As Int32, xlist As HashSet(Of HashSet(Of Int32)))
                             For Each x As HashSet(Of Int32) In xlist
                                 If x.Contains(y) Then
                                     Return False
                                 End If
                             Next
                             Return True
                         End Function
            If Not inPeak(task.Key, peaklist) Then
                Return False
            End If
            Return bCandidate
        Catch ex As Exception
            Throw
        End Try
    End Function
    Private Function GetPreListNew(ByVal PL As HashSet(Of HashSet(Of Int32)), ByVal peakpos As Int32, al As HashSet(Of Int32), ByVal proj As clsProject) As HashSet(Of Int32)
        Try
            Dim preList As New HashSet(Of Int32)
            Dim i As Int32 = 0
            Dim lp As Int32 = PL(peakpos).Last
            Dim preOfPeak =
                Function(peak As HashSet(Of Int32), itm As Int32, pr As clsProject) As Boolean
                    Try
                        For Each p As Int32 In peak
                            If pr.TasksA(p).AggPre.Contains(itm) Then
                                Return True
                                'is pre of a peak
                            End If
                        Next
                        Return False

                    Catch ex As Exception
                        Throw
                    End Try
                End Function
            Dim isPeak =
                Function(peaklist As HashSet(Of HashSet(Of Int32)), pp As Int32, itm As Int32) As Boolean
                    Try
                        'am i a peak?
                        Dim y As Int32
                        Dim count = peaklist.Count - 1
                        For y = pp To count
                            If peaklist(y).Contains(itm) Then
                                Return True
                            End If
                        Next
                        Return False
                    Catch ex As Exception
                        Throw
                    End Try
                End Function
            Dim potentielPre As New HashSet(Of Int32)
            For Each p As Int32 In PL(peakpos)
                Dim pTask As clsTask = proj.TasksA(p)
                For Each pre As Int32 In pTask.AggPre
                    If Not potentielPre.Contains(pre) Then
                        If Not isPeak(PL, peakpos, pre) Then
                            potentielPre.Add(pre)
                        End If
                    End If
                Next
            Next

            For Each a In al
                If potentielPre.Contains(a) Then
                    preList.Add(a)
                End If
            Next
            Return preList
        Catch ex As Exception
            Throw
        End Try
    End Function

    Private Function GetPreList(ByVal start As Int32, ByVal peak As HashSet(Of Int32), taskList() As clsTask, activityList As HashSet(Of Int32)) As HashSet(Of Int32)
        Try
            Dim preList As New HashSet(Of Int32)
            Dim IsPreOfPeak =
                Function(activity As Int32,
                        p As HashSet(Of Int32), l() As clsTask)
                    Try
                        For Each x As Int32 In p
                            If x = activity Then
                                'do not add peaks itself to the list
                                Return False
                            End If
                            For Each pre As Int32 In l(x).Pre
                                If activity = pre Then
                                    Return True
                                End If
                            Next
                        Next
                        Return False
                    Catch ex As Exception
                        Throw
                    End Try
                End Function
            For a As Int32 = start To activityList.Count - 1

                If IsPreOfPeak(activityList(a), peak, taskList) Then
                    If activityList(a) > 0 Then
                        preList.Add(activityList(a))
                    End If
                End If
            Next
            Return preList
        Catch ex As Exception
            Throw
        End Try
    End Function
    Private Function GenerateChilds(ByVal pair As clsProjectPair, ByVal treshold As Decimal, ByVal res_hash As Dictionary(Of Int32, Int32()),
                                    ByVal lTreshold As Single, ByVal uTreshold As Single, ByRef clonelist As HashSet(Of Int32)) As HashSet(Of clsProjectPair)
        Try

            Dim ret As New HashSet(Of clsProjectPair)
            Dim son As clsProject = pair.father.Clone
            Dim daugther As clsProject = pair.mother.Clone
            Dim regret As New clsRegretCalc
            Dim childs() As eChild = New eChild() {eChild.son, eChild.daughter}
            For Each child In childs
                Dim newActivityList As New HashSet(Of Int32)
                Dim peakParent As clsProject = If(child = eChild.son, pair.father, pair.mother)
                Dim parent As clsProject = If(child = eChild.son, pair.mother, pair.father)
                'Dim peakList As HashSet(Of HashSet(Of Int32)) = GetPeaks(peakParent, treshold, 0, 0)
                ' Dim peakList As HashSet(Of HashSet(Of Int32)) = GetPeaks(peakParent, Zufallszahl(lTreshold, uTreshold), 0, 0)
                Dim peakList As HashSet(Of HashSet(Of Int32))
                Dim allPs As Single = 0
                If peakDebels Then
                    peakList = GetPeaksDebels(peakParent)
                Else
                    If peakFangWang Then
                        peakList = GetPeaksFangWang(peakParent)
                    Else
                        peakList = GetPeaks(peakParent, 0, lTreshold, uTreshold, allPs)
                    End If

                End If


                Dim h As Int32 = 0
                Dim childProj As clsProject = Nothing
                Dim actList As New HashSet(Of Int32) '= DeepClone(parent.ActivtyList) => slow!!
                parent.ActivtyList.ToList.ForEach(Sub(item)
                                                      actList.Add(item)
                                                  End Sub)
                Dim span = 0
                ' peakList = New HashSet(Of Hashset(of Int32))
                Dim pp As Int32 = 0
                If usePeaks AndAlso peakList.Count > 0 Then
                    'Debug.Print("PEAK " & peakList.Count)
                    For Each peak As HashSet(Of Int32) In peakList
                        Dim firstPeakItem As Int32 = peak.ElementAt(0)
                        'Dim lastPeakItem As Int32 = peak.ElementAt(peak.Count - 1)
                        'before Peaks in List
                        Dim x As Long = 0
                        Dim peakPosts As New HashSet(Of Int32)
                        Do While Not peak.Contains(actList(0 + x))
                            'activity no peak
                            If Not x <= actList.Count - 1 Then
                                Exit Do
                            End If
                            Dim act = actList(0 + x)
                            Dim t As clsTask = parent.TasksA(act)
                            If IsCandidate(actList, t, peakList) And Not peakPosts.Contains(act) Then
                                'no peak or post of peak
                                If act = 0 Then
                                    Throw New Exception("0")
                                End If
                                If Not newActivityList.Contains(act) Then
                                    newActivityList.Add(act)
                                    actList.Remove(actList(0 + x))
                                End If
                            Else
                                Dim peakFromOther As clsTask = parent.TasksA(act)
                                For Each post As Int32 In peakFromOther.Post
                                    If Not peakPosts.Contains(post) Then
                                        peakPosts.Add(post)
                                    End If
                                Next
                                x += 1
                            End If
                        Loop
                        'pres of peaks
                        ' Dim preList As HashSet(Of Int32) = GetPreList(0, peak, parent.TasksA, actList)
                        Dim preList As HashSet(Of Int32) = GetPreListNew(peakList, pp, actList, parent)
                        For j As Int32 = 0 To preList.Count - 1
                            If IsCandidate(actList, parent.TasksA(preList(j)), peakList) Then
                                If preList(j) = 0 Then
                                    Throw New Exception("0")
                                End If
                                If Not newActivityList.Contains(preList(j)) Then
                                    newActivityList.Add(preList(j))
                                    actList.Remove(preList(j))
                                End If
                            End If
                        Next
                        'peaks
                        For j As Int32 = 0 To peak.Count - 1
                            newActivityList.Add(peak(j))
                            actList.Remove(peak(j))
                        Next
                        pp += 1
                    Next
                    Dim b As Int32 = 0
                    Do While b <= actList.Count - 1
                        If Not newActivityList.Contains(actList(b)) Then
                            newActivityList.Add(actList(b))
                        End If
                        b += 1
                    Loop
                    childProj = If(child = eChild.son, son, daugther)
                    childProj.ActivtyList = newActivityList
                    '  span = _ALtoSCH(newActivityList, childProj, res_hash)
                Else
                    span = parent.Fitness
                    childProj = parent.Clone(False)
                    newActivityList = childProj.ActivtyList
                End If
                childProj.Peaks = peakList.Count
                'Dim diagram(diagrams.Keys.Count - 1)()() As Int32
                'Dim c As Int32 = 0
                'For Each key As String In diagrams.Keys
                '    diagram(c) = diagrams(key)
                '    c += 1
                'Next
                'clsDiagrammCreator.WriteFile("C:\temp\makespan_child_1.htm", diagram, childProj)
                If randomType = 1 Then
                    If randInit Then Randomize()
                End If
                ' r = rand.Next(19, 31) / 100
                'r = 0.95
                Dim pMutation = r
                Dim tempList() As Int32 = newActivityList.ToArray
                Dim bChanged As Boolean = False
                'Dim swaplist As New HashSet(Of Int32)
                For i = 1 To tempList.Count - 3
                    Dim t2 As clsTask = childProj.TasksA(tempList(i + 1))
                    Dim t1 As clsTask = childProj.TasksA(tempList(i))
                    Dim bSwappable As Boolean = True
                    For Each pre As Int32 In t2.Pre
                        If t1.Key = pre Then
                            'wenn t1 ein pre von t2, swap verboten
                            bSwappable = False
                            Exit For
                        End If
                    Next
                    If bSwappable Then
                        Dim bswap As Boolean = False
                        ' If Not swaplist.Contains(tempList(i + 1)) Then
                        ' swap once
                        If randomType = 1 Then
                            If Rnd() <= pMutation Then
                                bswap = True
                            End If
                        Else
                            If randInit Then RandNum = New Random
                            If RandNum.NextDouble() <= pMutation Then
                                bswap = True
                            End If
                        End If

                        If bswap Then
                            '       swaplist.Add(tempList(i))
                            Dim t2V As Int32 = tempList(i + 1)
                            tempList(i + 1) = tempList(i)
                            tempList(i) = t2V
                            bChanged = True
                            'swapped
                        End If
                    End If
                    'End If
                Next
                If bChanged Then
                    newActivityList = New HashSet(Of Int32)
                    For i = 0 To tempList.Count - 1
                        newActivityList.Add(tempList(i))
                    Next
                    childProj.ActivtyList = newActivityList
                    Dim badd = True
                    'If detectClones Then
                    '    badd = IsClone(clonelist, newActivityList)
                    'End If
                    If badd Then
                        Dim span2 = _ALtoSCH(newActivityList, childProj, res_hash)
                        'Testdoku
                        'Dim span2 = makespan.CalcMakeSpan(newActivityList, childProj, diagrams, clsMakeSpanWithRes.eDirection.Left, False)
                        span = span2
                    End If
                End If
                If usePeaks AndAlso peakList.Count > 0 Then
                    If Not bChanged Then
                        Dim badd = True
                        'If detectClones Then
                        '    badd = IsClone(clonelist, newActivityList)
                        'End If
                        If badd Then
                            span = _ALtoSCH(newActivityList, childProj, res_hash)
                        End If
                    End If
                End If
                childProj.Fitness = span
                childProj.PeakSum = allPs
                childProj.Generation = 1
                childProj.GenerationType &= If(child = eChild.son, "_son", "_daughter")
                If (child = eChild.son) Then
                    son = childProj
                Else
                    daugther = childProj
                End If
                Try
                    Dim rightProj As clsProject = childProj.Clone(False, True)
                    Dim rightJList As HashSet(Of Int32) ' = regret.Justify_Valls(rightProj, clsRegretCalc.eJustifyDirection.Right, New Dictionary(Of String, Int32()()), res_hash)
                    If justifyEx Then
                        rightProj.GenerationType &= "_RightJustifiedEx"
                        rightJList = regret.Justify_Valls_byEx(rightProj, clsRegretCalc.eJustifyDirection.Right, New Dictionary(Of String, Int32()()), res_hash)
                    Else
                        rightProj.GenerationType &= "_RightJustified"
                        rightJList = regret.Justify_Valls(rightProj, clsRegretCalc.eJustifyDirection.Right, New Dictionary(Of String, Int32()()), res_hash)
                    End If
                    Dim leftProj As clsProject
                    If justifyLeftType = 1 Then
                        leftProj = childProj.Clone
                        leftProj.ActivtyList = New HashSet(Of Int32)
                        _ALtoSCH(rightJList, leftProj, res_hash)
                    Else
                        Dim leftJList As HashSet(Of Int32)
                        leftProj = rightProj.Clone(False, True)
                        If justifyEx Then
                            leftProj.GenerationType &= "_LeftJustifiedEx"
                            leftJList = regret.Justify_Valls_byEx(leftProj, clsRegretCalc.eJustifyDirection.Left, New Dictionary(Of String, Int32()()), res_hash)
                        Else
                            leftProj.GenerationType &= "_LeftJustified"
                            leftJList = regret.Justify_Valls(leftProj, clsRegretCalc.eJustifyDirection.Left, New Dictionary(Of String, Int32()()), res_hash)
                        End If
                        span = leftProj.TasksA.Last.PlanedAt
                    End If
                    leftProj.GenerationType &= "_LeftJustified" & If(justifyEx, "Ex", "")
                    ret.Add(New clsProjectPair With {.father = leftProj, .mother = rightProj})
                Catch ex As Exception
                    ret.Add(New clsProjectPair With {.father = childProj.Clone(False), .mother = childProj.Clone(False)})
                    Debug.Print("Justify Infeasible")
                    'keine aufnehmen wenn justify infeasible falsch
                End Try
                'End Sub)
            Next

            ret.Add(New clsProjectPair With {.father = son, .mother = daugther})
            Return ret
        Catch ex As Exception
            Throw
        End Try
    End Function

    Private Function GetPeaksFangWang(ByVal parent As clsProject) As HashSet(Of HashSet(Of Int32))
        Try
            Dim peaklist As New HashSet(Of HashSet(Of Int32))
            Dim rescount As Int32 = parent.RenewableResources.Count - 1
            Dim maxres(rescount) As Int32
            Dim i As Int32 = 0
            Dim allPeaks As New HashSet(Of Int32)
            For Each res As String In parent.RenewableResources.Keys
                maxres(i) = parent.RenewableResources(res) ' - 1
                i += 1
            Next
            Dim len = 0
            Dim pos1 As Int32 = 0
            Dim pos2 As Int32 = 0
            Dim iter() As Int32
            Dim pos1W As Int32
            Dim pos2W As Int32
            Dim counter As Int32
            Select Case peakFangWangType
                Case 1
                    pos1 = RandNum.Next(0.15 * parent.Fitness, 0.35 * parent.Fitness)
                    pos2 = RandNum.Next(0.65 * parent.Fitness, 0.75 * parent.Fitness)
                    iter = New Int32() {1}
                Case 2
                    pos1 = RandNum.Next(0.25 * parent.Fitness, 0.65 * parent.Fitness)
                    pos2 = RandNum.Next(0.75 * parent.Fitness, 0.85 * parent.Fitness)
                    iter = New Int32() {1}
                Case 3
                    Dim solutionQual As Int32 = parent.Fitness / parent.MPMTime


                    'counter = 2 * solutionQual * (parent.ActivtyList.Count - 2) / 30   '33,9

                    'counter = 0.5 * solutionQual * (parent.ActivtyList.Count - 2) / 30  '33,6
                    counter = ((parent.ActivtyList.Count - 2) / 30) '+ 1
                    ' counter = 1
                    ReDim iter(counter - 1)
                    pos1W = RandNum.Next((0.25 / counter) * parent.Fitness, (0.65 / counter) * parent.Fitness)
                    pos2W = RandNum.Next((0.75 / counter) * parent.Fitness, (0.85 / counter) * parent.Fitness)
                    For x As Int32 = 0 To iter.Length - 1
                        iter(x) = x + 1
                    Next
                Case Else
                    Throw New NotImplementedException("Peak Fang/Wang mode unknown")
            End Select

            Dim iterCount As Int32 = iter.Length
            Dim iterStep As Int32 = parent.Fitness / iterCount

            For Each it As Int32 In iter

                If peakFangWangType = 3 Then
                    If it > 1 Then
                        iterStep += If(RandNum.NextDouble > 0.5, -1, 1) * RandNum.Next(0, 5)
                        pos1 = pos1W + (iterStep * (it - 1))
                        pos2 = pos2W + (iterStep * (it - 1))

                        ' pos1 = RandNum.Next(((0.25 / iterCount) + ((it - 1) / iterCount)) * parent.Fitness, ((0.65 / iterCount) + ((it - 1) / iterCount)) * parent.Fitness)
                        ' pos2 = RandNum.Next(((0.75 / iterCount) + ((it - 1) / iterCount)) * parent.Fitness, ((0.85 / iterCount) + ((it - 1) / iterCount)) * parent.Fitness)
                    Else
                        pos1 = pos1W
                        pos2 = pos2W
                    End If
                End If

                Dim bestPeak As Single = 1
                Dim bestPeakNr As Int32 = 0
                Dim a As Long = pos1 + 1
                Do While a < parent.Fitness
                    'iterate intervall with len of random nr.
                    Dim peakSum As Single = 0
                    For k As Int32 = 0 To rescount
                        peakSum += (parent.PeakResource(k)(a) / maxres(k))
                    Next
                    Dim peakCalc As Single = peakSum / (rescount + 1)
                    'If peakCalc > bestPeak Then ' 36,1 !!
                    If peakCalc < bestPeak Then
                        bestPeak = peakCalc
                        bestPeakNr = a
                    End If
                    If a >= pos2 Then
                        'nicht ganz bis zum ende gehen
                        Exit Do
                    End If
                    a += 1
                Loop


                Dim list As New HashSet(Of Int32)
                'search on every point of the best peak area and add task
                For t As Int32 = pos1 To bestPeakNr - 1
                    For Each act As Int32 In parent.ActivtyList
                        If Not allPeaks.Contains(act) Then 'be only part of one peak
                            Dim task As clsTask = parent.TasksA(act)
                            Dim key As Int32 = task.Key
                            If t >= task.PlanedAt And t < task.PlanedAt + task.Duration Then
                                If Not list.Contains(key) Then
                                    list.Add(key)
                                End If
                            End If
                        End If
                    Next
                Next
                If list.Count > 0 Then
                    peaklist.Add(list)
                End If

            Next

            Return peaklist
        Catch ex As Exception
            Throw
        End Try
    End Function
    Private Function GetPeaksDebels(ByVal parent As clsProject) As HashSet(Of HashSet(Of Int32))
        Try

            Dim peaklist As New HashSet(Of HashSet(Of Int32))
            Dim rescount As Int32 = parent.RenewableResources.Count - 1
            Dim maxres(rescount) As Int32
            Dim i As Int32 = 0
            For Each res As String In parent.RenewableResources.Keys
                maxres(i) = parent.RenewableResources(res) ' - 1
                i += 1
            Next
            Dim len As Int32 = RandNum.Next(0.25 * parent.Fitness, 0.75 * parent.Fitness)
            Dim pos1 As Int32 = 0
            Dim bestPeak As Single = 0
            Dim bestPeakNr As Int32 = 0

            Do While parent.Fitness - len > pos1
                'iterate intervall with len of random nr.
                Dim tru As Single = 0
                For t As Int32 = pos1 To pos1 + len - 1
                    Dim peakSum As Single = 0
                    For k As Int32 = 0 To rescount
                        peakSum += (parent.PeakResource(k)(t) / maxres(k))
                    Next
                    Dim peakCalc As Single = peakSum / (rescount + 1)
                    tru += peakCalc

                Next
                If tru > bestPeak Then
                    bestPeak = tru
                    bestPeakNr = pos1
                End If
                pos1 += 1
            Loop

            Dim list As New HashSet(Of Int32)
            'search on every point of the best peak area and add task
            For t As Int32 = bestPeakNr To bestPeakNr + len - 1
                For Each act As Int32 In parent.ActivtyList
                    Dim task As clsTask = parent.TasksA(act)
                    Dim key As Int32 = task.Key
                    If t >= task.PlanedAt And t < task.PlanedAt + task.Duration Then
                        If Not list.Contains(key) Then
                            list.Add(key)
                        End If
                    End If

                Next
            Next
            peaklist.Add(list)
            Return peaklist
        Catch ex As Exception
            Throw
        End Try
    End Function
    Private Function GetPeaks(ByVal parent As clsProject, ByVal treshold As Decimal, lTreshold As Single, uTreshold As Single, ByRef allPs As Single) As HashSet(Of HashSet(Of Int32))
        Try
            Dim peaklist As New HashSet(Of HashSet(Of Int32))
            Dim len As Int32 = parent.Fitness - 1
            Dim allPeakSum As Single
            Dim rescount As Int32 = parent.RenewableResources.Count - 1
            Dim list As New HashSet(Of Int32)
            Dim allPeaks As New HashSet(Of Int32)
            Dim maxres(rescount) As Int32
            Dim i As Int32 = 0
            For Each res As String In parent.RenewableResources.Keys
                maxres(i) = parent.RenewableResources(res) ' - 1
                i += 1
            Next
            '    treshold = Zufallszahl(lTreshold, uTreshold) ' GetLevel(lTreshold, uTreshold)
            For t As Int32 = 0 To len
                Dim peakSum As Single = 0
                For k As Int32 = 0 To rescount
                    peakSum += (parent.PeakResource(k)(t) / maxres(k))
                Next
                Dim peakCalc As Single = peakSum / (rescount + 1)
                allPeakSum += peakCalc
                treshold = Zufallszahl(lTreshold, uTreshold) ' GetLevel(lTreshold, uTreshold)

                If peakCalc >= treshold Then
                    For Each act As Int32 In parent.ActivtyList
                        Dim task As clsTask = parent.TasksA(act)
                        Dim key As Int32 = task.Key
                        If Not allPeaks.Contains(key) Then
                            If t >= task.PlanedAt And t < task.PlanedAt + task.Duration Then
                                If Not list.Contains(key) Then
                                    list.Add(key)
                                    allPeaks.Add(key)
                                End If
                            End If
                        End If
                    Next
                Else
                    If list.Count > 0 Then
                        If peakLimitConst > 0 Then
                            If peaklist.Count >= peakLimitConst Then
                                Exit For
                            End If
                        End If

                        peaklist.Add(list)
                        list = New HashSet(Of Int32)
                    End If
                End If
            Next

            allPs = allPeakSum / len

            If peaklimitDyn Then
                'remove half of the peaks 
                Dim tempL As New HashSet(Of HashSet(Of Int32))
                For a = 0 To peaklist.Count - 1 Step 2
                    tempL.Add(peaklist(a))
                Next
                peaklist = tempL
            End If

            Return peaklist
        Catch ex As Exception
            Throw
        End Try

    End Function
End Class
